﻿#include "Collision.h"


//-------------------------------------------------------------
//tinh thoi gian va huong va cham
//tra ve (0, 1) neu va cham, tra ve 1 neu khong va cham
//normalx va normaly dung de xac dinh mat va cham
//MAT VA CHAM CHI DUNG VOI TRUONG HOP 1 VAT DI CHUYEN, 1 VAT DUNG YEN
//--------------------------------------------------------------
float sweptAABB(Box box1, Box box2, float &normalx, float &normaly)
{
	//khoang cach vao mien dung do
	float xInvEntry, yInvEntry;

	//khoang cach thoat khoi mien dung do
	float xInvExit, yInvExit;

	if (box1.fVx > 0)
	{
		xInvEntry = box2.iX - (box1.iX + box1.iWidth);
		xInvExit = (box2.iX + box2.iWidth) - box1.iX;
	}
	else
	{
		xInvEntry = (box2.iX + box2.iWidth) - box1.iX;
		xInvExit = box2.iX - (box1.iX + box1.iWidth);
	}

	if (box1.fVy > 0)
	{
		yInvEntry = (box2.iY - box2.iHeight) - box1.iY;
		yInvExit = box2.iY - (box1.iY - box1.iHeight);

	}
	else
	{
		yInvExit = (box2.iY - box2.iHeight) - box1.iY;
		yInvEntry = box2.iY - (box1.iY - box1.iHeight);
	}

	//thoi gian vao mien va cham
	float xEntry, yEntry;

	//thoi gian ra khoi mien va cham
	float xExit, yExit;

	//neu van toc la 0 thi thoi gian va cham la vo cuc
	if (box1.fVx == 0)
	{
		xEntry = -std::numeric_limits<float>::infinity();
		xExit = std::numeric_limits<float>::infinity();
	}
	else
	{
		//thoi gian = quang duong / van toc
		xEntry = xInvEntry / box1.fVx;
		xExit = xInvExit / box1.fVx;
	}

	//neu van toc la 0 thi thoi gian va cham la vo cuc
	if (box1.fVy == 0)
	{
		yEntry = -std::numeric_limits<float>::infinity();
		yExit = std::numeric_limits<float>::infinity();
	}
	else
	{
		//thoi gian = quang duong / van toc
		yEntry = yInvEntry / box1.fVy;
		yExit = yInvExit / box1.fVy;
	}

	//tim thoi gian bat dau va cham la thoi gian lon nhat
	float entryTime = max(xEntry, yEntry);

	//thoi gian ket thuc va cham la thoi gian nho nhat
	float exitTime = min(xExit, yExit);

	//truong hop khong xay ra va cham
	if (entryTime > exitTime)
	{
		normalx = 0.0f;
		normaly = 0.0f;
		return 1.0f;
	}

	//truong hop xay ra va cham
	else
	{
		//va cham theo phuong ngang
		if (xEntry > yEntry)
		{
			normaly = 0;
			if (xInvEntry < 0.0f)
				//ben phai vat 1
				normalx = 1.0f;
			else
				//ben trai vat 1
				normalx = -1.0f;

		}
		//va cham theo phuong thang dung
		else
		{
			normalx = 0;
			if (yInvEntry < 0.0f)
				//ben duoi vat 1
				normaly = 1.0f;
			else
				//ben tren vat 1
				normaly = -1.0f;
		}
	}
	return entryTime;
}

//---------------------------------------------
//lay vi tri tiep theo cua box
//---------------------------------------------
Box getSweptBroadphaseBox(Box box)
{
	Box broadphasebox;

	broadphasebox.iX = box.fVx > 0 ? box.iX : box.iX + box.fVx;
	broadphasebox.iY = box.fVy > 0 ? box.iY : box.iY + box.fVy;
	broadphasebox.iWidth = box.fVx > 0 ? box.fVx + box.iWidth : box.iWidth - box.fVx;
	broadphasebox.iHeight = box.fVy > 0 ? box.fVy + box.iHeight : box.iHeight - box.fVy;
	broadphasebox.fVx = 0;
	broadphasebox.fVy = 0;

	return broadphasebox;
}

//----------------------------------------------------------
//kiem tra truoc mot so truong hop co the xay ra va cham
//----------------------------------------------------------
bool AABBCheck(Box box1, Box box2)
{
	if (box1.iX + box1.iWidth < box2.iX || box1.iX > box2.iX + box2.iWidth || box1.iY - box1.iHeight > box2.iY || box1.iY < box2.iY - box2.iHeight)
		return false;
	return true;
}

//HAM NAY CHUA SU DUNG
//--------------------------------------------------------------------------
//kiem tra va tranh va cham
//tra ve true neu va cham
//movex va movey la khoang cach ma b1 phai di chuyen de tranh va cham
//--------------------------------------------------------------------------
bool AABB(Box b1, Box b2, float& moveX, float& moveY)
{
	moveX = moveY = 0.0f;

	float l = b2.iX - (b1.iX + b1.iWidth);	//dentryx(nếu vx >0)
	float r = (b2.iX + b2.iWidth) - b1.iX;	//denxitx(nếu vx > 0)
	float t = b2.iY - (b1.iY + b1.iHeight);	//dentryy(nếu vy > 0)
	float b = (b2.iY + b2.iHeight) - b1.iY;	//dexity(nếu vy > )

	// chưa xảy ra va chạm
	if (l > 0 || r < 0 || t > 0 || b < 0)
		return false;

	// tính dentry của x và y với mọi vx, vy
	moveX = abs(l) < r ? l : r;		//lấy dentryx
	moveY = abs(t) < b ? t : b;		//lấy dexityy

	// sử dụng biến move nào nhỏ hơn, biến còn lại cho bằng 0, 
	if (abs(moveX) < abs(moveY))
		moveY = 0.0f;
	else
		moveX = 0.0f;
	return true;
}

//------------------------------------------------
//ham xet va cham
//tra ve true neu va cham
//normalx va normaly dung de xet mat va cham
//------------------------------------------------
bool isCollide(Box box, Box block, float &normalx, float &normaly)
{
	Box box1, box2;
	bool isExchange = false;

	//vat 2 dung yen
	if (block.fVx == 0 && block.fVy == 0)
	{
		box1 = box;
		box2 = block;
	}

	//vat 1 dung yen, doi vat 1 thanh vat 2
	else if (box.fVx == 0 && box.fVy == 0)
	{
		box1 = block;
		box2 = box;
		isExchange = true;
	}

	//ca 2 vat deu co van toc # 0
	else
	{
		box1 = box;
		box2 = block;

		//khac huong cong van toc
		//cung huong tru van toc
		if (box.fVx * block.fVx < 0)
			box1.fVx = box.fVx + block.fVx;
		else
			box1.fVx = box.fVx - block.fVx;

		//khac huong cong van toc
		//cung huong tru van toc
		if (box.fVy * block.fVy < 0)
			box1.fVy = box.fVy + block.fVy;
		else
			box1.fVy = box.fVy - block.fVy;
	}

	//lay box ke tiep cua vat 1
	Box broadphasebox = getSweptBroadphaseBox(box1);

	//kiem tra box ke tiep co va cham khong
	if (AABBCheck(broadphasebox, box2))
	{
		//thoi gian va cham nay chua dung den
		float collisiontime = sweptAABB(box1, box2, normalx, normaly);

		if (collisiontime < 1.0f)
		{
			//ben trai vat 2 la ben phai vat 1 va nguoc lai
			//ben tren vat 2 la ben phai vat 1 va nguoc lai 
			if (isExchange)
			{
				normalx *= -1;
				normaly *= -1;
			}
			return true;
		}
	}

	return false;
}